// Pawn.cpp
//
// Created By: Jeremy Butler
// Created On: 31-Mar-2011

#include <sstream>

#include "Pawn.h"
#include "UnitTest.h"
#include "Board.h"
#include "ChessController.h"
using namespace std;

Pawn::Pawn() : Piece() {
  return;
}

Pawn::Pawn(const Color _color) : Piece(_color, PAWN){
  return;
}

Pawn::Pawn(const Pawn & other) : Piece(other) {
  return;
}

Pawn * Pawn::Clone() const{
  return new Pawn(*this);
}

Pawn::~Pawn(){
  return;
}

set<Location> Pawn::GetValidMoves(const Board & board, int row, int col, bool AllMoves) const{
  set<Location> validMoves;
  Location location;

  int direction = (color == WHITE) ? -1 : 1;
  int startRow = (color == WHITE) ? 6 : 1;

  try{
    if(board(row+direction*1,col) == NULL){
      location.Set(col,row+direction*1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }

  try{
    if(row == startRow && board(row+direction*2,col) == NULL
	&& board(row+direction*1,col) == NULL){
      location.Set(col,row+direction*2);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }

  try{
    if(board(row+direction*1,col-1) != NULL && board(row+direction*1,col-1)->GetColor() != color){
      location.Set(col-1,row+direction*1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }

  try{
    if(board(row+direction*1,col+1) != NULL && board(row+direction*1,col+1)->GetColor() != color){
      location.Set(col+1,row+direction*1);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }

  if(!AllMoves)
    board.RemoveCheckMoves(validMoves,row,col);

  return validMoves;
}

bool Pawn::Test(ostream & os){
  bool success = true;

  ChessView view;
  ChessController controller(view,0);

  controller.SetView(&view);
  view.SetController(&controller);
  
  controller.LoadGame("games/pawnTest.xml");

  set<Location> moves;

  moves = controller.model->GetValidMoves(6,0);

  TEST(moves.size() == 2);

  moves = controller.model->GetValidMoves(6,3);

  TEST(moves.size() == 4);

  moves = controller.model->GetValidMoves(6,5);

  TEST(moves.size() == 0);

  moves = controller.model->GetValidMoves(6,7);

  TEST(moves.size() == 1);

  moves = controller.model->GetValidMoves(4,4);

  TEST(moves.size() == 1);

  moves = controller.model->GetValidMoves(3,0);

  TEST(moves.size() == 2);

  moves = controller.model->GetValidMoves(3,2);

  TEST(moves.size() == 2);

  moves = controller.model->GetValidMoves(3,7);

  TEST(moves.size() == 1);

  moves = controller.model->GetValidMoves(1,1);

  TEST(moves.size() == 1);

  moves = controller.model->GetValidMoves(0,2);

  TEST(moves.size() == 0);

  return success;
}

string Pawn::ToString() const{
  stringstream str;
  
  string sColor;
  if(color == WHITE)
    sColor = "White";
  else if(color == BLACK)
    sColor = "Black";
  else
    sColor = "Colorless";

  str << sColor << " Pawn";

  return str.str();
}